#ifndef __H_COMPONENT_H__
#define __H_COMPONENT_H__
#include <memory>
#include <typeinfo>
#include <string>
#include <map>
#include "log.h"



class Component
{
public:
    template<typename T, class = typename std::enable_if<std::is_base_of<Component, T>::value>::type, typename... Args>
    static std::shared_ptr<T> Create(Args... args)
    {
        try
        {
            std::shared_ptr<T> t = std::make_shared<T>(args...);
            return t;
        }
        catch(const std::exception& e)
        {
            log_error("exception:%s", e.what());
        }
        catch(...)
        {
            log_error("unknown exception");
        }
        return nullptr;
    }

public:
    template<typename T, class = typename std::enable_if<std::is_base_of<Component, T>::value>::type>
    bool Add(std::string tag, std::shared_ptr<T> t)
    {
        std::shared_ptr<Component> c = std::dynamic_pointer_cast<Component>(t);
        if (c == nullptr)
        {
            return false;
        }
        return m_children.insert(std::make_pair(tag, c));
    }

    template<typename T, class = typename std::enable_if<std::is_base_of<Component, T>::value>::type>
    std::shared_ptr<T> Get(std::string tag)
    {
        auto it = m_children.find(tag);
        if (it == m_children.end())
        {
            return nullptr;
        }
        return std::dynamic_pointer_cast<T>(it->second);
    }

    void Remove(std::string tag)
    {
        m_children.erase(tag);
    }

public:
    virtual bool Init();
    virtual void Reload();
    virtual void Release(); 

private:
    std::map<std::string, std::shared_ptr<Component>> m_children;
};


#endif  // __H_COMPONENT_H__
